/**
 * @brief 主循环.
 * @version 1.1
 * @author 宋炜
 * @date 2023-5-18~2025-9-2
 *   2025-9-2  增加emit方法，方便发送命令
 */

#pragma once

#include <atomic>
#include "designM/eventDetail/dispatcher.hpp"
#if CMD_USE_SINGLETON
#    include "designM/singleton.hpp"
#endif
namespace wheels
{
	namespace dm
	{
		/// @brief
		/// @tparam cmdType 命令类型，要求这个类型支持拷贝构造，赋值拷贝;如果属实类则应该是可以
		///    作为方便检索的基础类型，比如整型数据。
		template< typename cmdType >
		class mainLoop
#if CMD_USE_SINGLETON
            : public singleton< mainLoop<cmdType> >
#endif
		{
		public:
			using cmd_type = typename std::remove_pointer< typename std::decay< cmdType >::type >::type;
			
			static_assert( std::is_integral< cmd_type >::value ||
				       std::is_enum<cmd_type >::value || (
					       std::is_class< cmd_type >::value && 
					       std::is_copy_assignable< cmd_type >::value &&
					       std::is_copy_constructible< cmd_type > ::value 
					       ) , "" );
			using dispatcher_t = dispatcher< cmd_type >;
		private:
			std::atomic< bool >   m_is_running__;
			std::atomic< long >   m_over_time__;
			std::unique_ptr< dispatcher< cmd_type > >   pt_dsptch__;
		public:
			mainLoop( long ovt = 10 ): m_is_running__( false ) , m_over_time__( ovt ){
#if CMD_USE_SINGLETON
				dispatcher<cmd_type>::create();
#else
				pt_dsptch__.reset( new dispatcher<cmd_type> );
#endif
			}
			mainLoop( const mainLoop& ){}
			virtual ~mainLoop(){
				stop();
			}
#if CMD_USE_SINGLETON
			template< typename dataType >
			void emit( const cmdType& cmd , dataType&& data , bool notify = true ){
				auto p_dsptch = dispatcher<cmdType>::get_shared();
				if( p_dsptch ){
					p_dsptch->emit( cmd , std::forward< dataType>( data ) , notify );
				}
			}
#else
			template< typename dataType >
			void emit( const cmdType& cmd , dataType&& data , bool notify = true ){
				if( pt_dsptch__ ){
					pt_dsptch__->emit( cmd , std::forward< dataType>( data ) , notify );
				}
			}
#endif
			inline bool start( bool sw ){
				if( sw ){
					return exec();
				}else{
					stop();
				}

				return true;
			}

			/**
			 * @brief 启动主循环
			 */
			bool exec(){
				if( m_is_running__ == true ) return true;
				
				m_is_running__ = true;
#if CMD_USE_SINGLETON
				dispatcher<cmdType> * p_dsptch = dispatcher<cmdType>::get();
#else
				dispatcher<cmdType> * p_dsptch = pt_dsptch__.get();
#endif
				if( p_dsptch == nullptr ) return false;
				
				while( m_is_running__.load() ){
					p_dsptch->dispatch( m_over_time__.load() );
				}
				MSG( "事件模式主线程停止" , TNORMAL );
				return true;
			}
			/**
			 * @brief 停止运行
			*/
			void stop(){
				if( m_is_running__ == false ) return;
				
				m_is_running__ = false;
#if CMD_USE_SINGLETON
				dispatcher<cmdType> * p_dsptch = dispatcher<cmdType>::get();
#else
				dispatcher<cmdType> * p_dsptch = pt_dsptch__.get();
#endif
				
				if( p_dsptch ){
					p_dsptch->clear();
				}
			}
			/**
			 * @brief 判断是否正在运行
			*/
			bool isRunning(){ return m_is_running__.load(); }
			/**
			* @brief 获取调度器
			*/
			dispatcher<cmdType> * getDispatch(){
#if CMD_USE_SINGLETON
				dispatcher<cmdType> * p_dsptch = dispatcher<cmdType>::get();
#else
				dispatcher<cmdType> * p_dsptch = pt_dsptch__.get();
#endif
				return p_dsptch;
			}
		};
#if CMD_USE_SINGLETON
#define IMP_CMD( cmdType )  IMP_SINGLETON( mainLoop< cmdType > ); \
		IMP_SINGLETON( dispatcher< cmdType> );
#endif
	}
}
